package org.terukusu.util;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

import android.util.Log;

/**
 * 便利メソッドの詰め合わせ。
 *
 * @author Teruhiko Kusunoki&lt;<a href="teru.kusu@gmail.com">teru.kusu@gmail.com</a>&gt;
 *
 */
public class Utils {
    private static final String TAG = Utils.class.getSimpleName();

	/**
	 * 新しいオブジェクトを生成します。
	 */
	protected Utils() {
	}

	/**
	 * バイト列を16進ダンプ形式に整形します。
	 * 文字列部分のエンコーディングにはデフォルトエンコーディングを使用します。
	 *
	 * @param data バイト列
	 * @return １６進ダンプ形式に整形された文字列
	 */
	public static String hexDump(byte[] data) {
		return hexDump(data, null);
	}

	/**
	 * バイト列を16進ダンプ形式に整形します。
	 *
	 * @param data バイト列
	 * @param encoding 文字列部のエンコーディング
	 * @return １６進ダンプ形式に整形された文字列
	 */
	public static String hexDump(byte[] data, String encoding) {
		StringBuilder sb = new StringBuilder();

		if (encoding == null) {
			encoding = System.getProperty("file.encoding");
		}

		final int bytesPerLine = 16;

		int i = 0;
		for (i = 0; i < data.length; i++) {
			if (i % bytesPerLine == 0) {
				if (i > 0) {
					sb.append("  ");
					try {
						sb.append(new String(data, i - bytesPerLine, bytesPerLine, encoding));
					} catch (UnsupportedEncodingException e) {
						throw new RuntimeException(e.getMessage(), e);
					}
					sb.append("\n");
				}
				sb.append(String.format("%08x:", i));
			} else if (i % 4 == 0) {
				sb.append(' ');
			}

			sb.append(String.format(" %02x", data[i]));
		}

		Log.v(TAG, "data size: " + data.length + ", dumped size: " + i);

		if (i % bytesPerLine != 0) {
			if (i / bytesPerLine > 0) {
				for (int j = i; j % bytesPerLine != 0; j++) {
					if (j % 4 == 0) {
						sb.append(" ");
					}
					sb.append("   ");
				}
			}
			sb.append("  ");
			try {
				sb.append(new String(data, i - i % bytesPerLine, i % bytesPerLine, encoding));
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
			sb.append("\n");
		}

		return sb.toString();
	}

	/**
	 * 文字列がからかどうかを取得します。
	 *
	 * @param str 文字列
	 * @return nullまたは空文字列ならばtrue
	 */
	public static boolean isStringEmpty(String str) {
	    return (str == null || str.length() == 0);
	}

	/**
	 * データ容量を人間が読みやすい補助単位付きの文字列に変換します。
	 *
	 * @param bytes データ容量
	 * @return 補助単位付きのファイルサイズ文字列
	 */
	public static String getHumanFriendlyBytes(long bytes) {
	    double size = bytes;
	    String unit = "bytes";

	    if (bytes >= 1024 * 1024 * 1024) {
	        unit = "GB";
	        size = size/(1024 * 1024 * 1024);
	    } else if (bytes >= 1024 * 1024) {
            unit = "MB";
            size = size/(1024 * 1024);
        } else if (bytes >= 1024) {
            unit = "KB";
            size = size/1024;
	    }

	    DecimalFormat df = new DecimalFormat("0.0");
	    String result = df.format(new BigDecimal(size).setScale(1, RoundingMode.HALF_UP)) + unit;

	    return result;
	}
}
